package com.prd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.prd.component.LoginRegisterFactory;
import com.prd.config.LoginInterceptor;
import com.prd.enums.BizCodeEnum;
import com.prd.enums.UserAuthenticcationTypeEnum;
import com.prd.enums.UserIsSetPwdTypeEnum;
import com.prd.model.LoginUser;
import com.prd.model.UserDO;
import com.prd.mapper.UserMapper;
import com.prd.request.UserLoginRequest;
import com.prd.request.UserRegisterRequest;
import com.prd.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.prd.util.CommonUtil;
import com.prd.util.JWTUtil;
import com.prd.util.JsonData;
import com.prd.vo.LoginRegisterVo;
import com.prd.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lizhaoyi
 * @since 2023-10-23
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, UserDO> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private LoginRegisterFactory loginRegisterFactory;

    /**
     * 用户注册
     * * 手机号验证码验证（TODO）
     * * 密码加密
     * * 账号唯一性检查
     * * 插入数据库
     *
     * @param registerRequest
     * @return
     */
    @Override
    public JsonData register(UserRegisterRequest registerRequest) {

        boolean checkCode = false;
        //校验验证码 TODO
        if (checkCode) {
            return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
        }

        UserDO userDO = new UserDO();
        BeanUtils.copyProperties(registerRequest, userDO);
        userDO.setCreateTime(LocalDateTime.now());
        //设置密码 生成秘钥 盐
        userDO.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
        //密码+盐处理
        String cryptPwd = Md5Crypt.md5Crypt(registerRequest.getPwd().getBytes(), userDO.getSecret());
        userDO.setPwd(cryptPwd);

        //账号唯一性检查
        if (checkUnique(userDO.getTelephone())) {

            int rows = userMapper.insert(userDO);
            log.info("rows:{},注册成功:{}", rows, userDO.toString());

            return JsonData.buildSuccess();
        } else {
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
        }
    }


    /**
     * 1、根据telephone去找有没这记录
     * 2、有的话，则用秘钥+用户传递的明文密码，进行加密，再和数据库的密文进行匹配
     *
     * @param userLoginRequest
     * @return
     */
    @Override
    public JsonData login(UserLoginRequest userLoginRequest) {

        List<UserDO> userDOList = userMapper.selectList(new QueryWrapper<UserDO>().eq("telephone", userLoginRequest.getTelephone()));
        if (userDOList != null && userDOList.size() == 1) {
            //已经注册
            UserDO userDO = userDOList.get(0);
            String cryptPwd = Md5Crypt.md5Crypt(userLoginRequest.getPwd().getBytes(), userDO.getSecret());
            if (cryptPwd.equals(userDO.getPwd())) {
                //登录成功,生成token
                LoginUser loginUser = LoginUser.builder().build();
                BeanUtils.copyProperties(userDO, loginUser);
                String accessToken = JWTUtil.geneJsonWebToken(loginUser);

                return JsonData.buildSuccess(accessToken);

            } else {
                return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
            }
        } else {
            //未注册
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
        }

    }

    /**
     * 查找用户详情
     *
     * @return
     */
    @Override
    public JsonData findUserDetail() {

        LoginUser loginUser = LoginInterceptor.threadLocal.get();

        UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().eq("id", loginUser.getId()));
        if (userDO == null) {
            return JsonData.buildError("用户不存在");
        }
        return JsonData.buildSuccess(userDO);
    }

    /**
     * 用户注册登录
     *
     * @param loginRegisterVo
     * @return
     */
    @Override
    public JsonData registerAndLogin(LoginRegisterVo loginRegisterVo) {

        return loginRegisterFactory.loginRegister(loginRegisterVo);
    }

    /**
     * 设置密码
     *
     * @param pwd
     * @return
     */
    @Override
    public JsonData setPassword(String pwd) {
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        UserDO userDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>().eq(UserDO::getId, loginUser.getId()));
        if (userDO == null) {
            return JsonData.buildError("用户不存在");
        }
        //设置密码 生成秘钥 盐
        userDO.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
        //密码+盐处理
        String cryptPwd = Md5Crypt.md5Crypt(pwd.getBytes(), userDO.getSecret());
        userDO.setPwd(cryptPwd);
        userDO.setIsSetPwd(UserIsSetPwdTypeEnum.YES.getCode());
        int rows = userMapper.updateById(userDO);
        return rows > 0 ? JsonData.buildSuccess() : JsonData.buildError("设置密码操作异常");
    }

    /**
     * 更新用户信息
     *
     * @param userVO
     * @return
     */
    @Override
    public JsonData updateUserInfo(UserVO userVO) {
        UserDO userDO = userMapper.selectById(userVO.getId());
        if (userDO == null) {
            return JsonData.buildError("用户不存在");
        }
        BeanUtils.copyProperties(userVO, userDO);
        if (StringUtils.isNotBlank(userVO.getPwd())) {
            //更新密码 生成秘钥 盐
            userDO.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
            //密码+盐处理
            String cryptPwd = Md5Crypt.md5Crypt(userVO.getPwd().getBytes(), userDO.getSecret());
            userDO.setPwd(cryptPwd);
        }
        userMapper.updateById(userDO);

        return JsonData.buildSuccess();
    }


    /**
     * 校验用户账号唯一
     *
     * @param telephone
     * @return
     */
    private boolean checkUnique(String telephone) {

        QueryWrapper queryWrapper = new QueryWrapper<UserDO>().eq("telephone", telephone);

        List<UserDO> list = userMapper.selectList(queryWrapper);

        return list.size() > 0 ? false : true;

    }

    /**
     * 调用身份认证接口
     *
     * @param name
     * @param idCardNum
     */
    private boolean authenticate(String name, String idCardNum) {
        try {
            // 构建URL
            String apiUrl = "http(s)://zid.market.alicloudapi.com/idcheck/Post";
            String queryParams = "?realName=" + name + "&cardNo=" + idCardNum;
            URL url = new URL(apiUrl + queryParams);
            // 创建连接
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            // 获取响应数据
            int responseCode = connection.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                StringBuffer response = new StringBuffer();
                String line;

                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                reader.close();
                // 处理认证结果
                return handleAuthenticationResult(response.toString());
            } else {
                // 处理请求失败情况
                log.error("请求失败，错误码：" + responseCode);
            }
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;

    }

    private boolean handleAuthenticationResult(String response) {
        try {
            JSONObject result = new JSONObject(response);
            boolean success = result.getBoolean("success");
            String message = result.getString("message");

            if (success) {
                // 认证成功
                log.info("认证成功");
                return true;
            } else {
                // 认证失败
                log.error("认证失败：" + message);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }
}
